
use super::*;
use axum::extract;
use crate::user;


/// get article
/// 判断 article 的 uid 与 session 里存的 user 的 id
/// 得作了 登录拦截，确保 session.get("user") 不为空
pub async fn check_article_uid<T>
    (
        session: &axum_session::Session<T>,
        article_id: u32
    ) -> bool
    where
        T: axum_session::DatabasePool + Clone + ::std::fmt::Debug + Sync + Send + 'static,
{
    let option = get_article_by_id(extract::Path(article_id)).await;
    if option.is_none() {
        eprintln!("文章{}读取失败", article_id);
        return false;
    }
    let article = option.as_ref().unwrap();

    let user: user::model::User = session.get("user").unwrap();
    if *article.get_author_uid() != *user.get_id() {
        eprintln!("文章作者非登录用户id={}", user.get_id());
        return false;
    }

    true
}



/// "/get/:id"
/// get
pub async fn get_article_by_id(extract::Path(id): extract::Path<u32>) -> extract::Json<Option<model::Article>>
{
    let rb = crate::db::get_rbatis();
    let result = model::Article::select_by_id(rb, &id.to_string()).await;
    return if let Result::Ok(option) = result {
        if option.is_none() {
            eprintln!("result is none");
            return extract::Json(Option::None);
        }
        let mut article = option.unwrap();
        if let Err(e) = article.read_text() {
            eprintln!("文章内容读取失败\n{}", e);
            return extract::Json(Option::None);
        }
        extract::Json(Option::Some(article))
    } else {
        eprintln!("{}", result.err().unwrap());
        extract::Json(Option::None)
    }
}


/// "/delete/:id"
/// get
/// 得作 登录拦截
pub async fn delete_article_by_id
    (
        session: axum_session::Session<axum_session::SessionPgPool>,
        extract::Path(id): extract::Path<u32>
    ) -> axum::response::Html<String>
{
    // 判断有无登录
    if !user::authentication::authenticate_user_login(&session) {
        return axum::response::Html(rust_i18n::t!("user.authentication.not_logged"));
    }

    let rb = crate::db::get_rbatis();
    let success = axum::response::Html(rust_i18n::t!("article.delete.success"));
    let failed = axum::response::Html(rust_i18n::t!("article.delete.failed.default"));

    // 得作了 登录拦截，确保 session.get("user") 不为空
    if !check_article_uid(&session, id).await {
        return failed;
    }

    let mut tx = if let Ok(tx) = rb.acquire_begin().await {
        tx
    } else { return failed; };
    let result = model::Article::delete_by_id(rb, &id.to_string()).await;
    if let Err(e) = result {
        eprintln!("database delete error\n{}", e);
        tx.commit().await.unwrap();
        tx.rollback().await.unwrap();
        return failed;
    }

    tx.commit().await.unwrap();
    success
}



/// "/upload"
/// post
/// 得作 登录拦截
pub async fn upload_article
    (
        session: axum_session::Session<axum_session::SessionPgPool>,
        axum::Json(mut article): axum::Json<model::Article>
    ) -> axum::response::Html<String>
{
    // 判断有无登录
    if !user::authentication::authenticate_user_login(&session) {
        return axum::response::Html(rust_i18n::t!("user.authentication.not_logged"));
    }

    let rb = crate::db::get_rbatis();
    let success = axum::response::Html(rust_i18n::t!("article.upload.success"));
    let failed = axum::response::Html(rust_i18n::t!("article.upload.failed.default"));

    let mut tx = if let Ok(tx) = rb.acquire_begin().await {
        tx
    } else { return failed; };

    if article.get_title().is_none() { return failed; }
    let result = model::Article::insert(rb, &article).await;
    if let Ok(_) = result {

        // 查找article的id
        // SELECT column_name FROM table_name
        // ORDER BY column_name DESC
        // LIMIT 1;
        let result: Result<u32, rbatis::error::Error> = rb.query_decode("SELECT id FROM article ORDER BY id DESC LIMIT 1;", vec![]).await;
        if let Err(e) = result {
            eprintln!("select error\n{}", e);
            tx.commit().await.unwrap();
            tx.rollback().await.unwrap();
        } else { article.set_id(result.unwrap()); }// 这儿已经insert，所以最后一个就是这个

    } else {
        eprintln!("database insert error\n{}", result.unwrap_err());
        return failed;
    }
    // 保存article内容
    if let Err(e) = article.save_text() {
        eprintln!("save content error\n{}", e);
        tx.commit().await.unwrap();
        tx.rollback().await.unwrap();
        return failed;
    }


    tx.commit().await.unwrap();
    success
}


/// "/update"
/// post
/// 得作 登录拦截
pub async fn update_article
    (
        session: axum_session::Session<axum_session::SessionPgPool>,
        axum::Json(article): axum::Json<model::Article>
    ) -> axum::response::Html<String>
{
    // 判断有无登录
    if !user::authentication::authenticate_user_login(&session) {
        return axum::response::Html(rust_i18n::t!("user.authentication.not_logged"));
    }

    let rb = crate::db::get_rbatis();
    let success = axum::response::Html(rust_i18n::t!("article.update.success"));
    let failed = axum::response::Html(rust_i18n::t!("article.update.failed.default"));

    // 得作了 登录拦截，确保 session.get("user") 不为空
    if !check_article_uid(&session, article.get_id().clone()).await {
        return failed;
    }

    let mut tx = if let Ok(tx) = rb.acquire_begin().await {
        tx
    } else { return failed; };
    let result = model::Article::update_by_id(rb, &article, &article.get_id().to_string()).await;
    if let Err(e) = result {
        eprintln!("database update error\n{}", e);
        tx.commit().await.unwrap();
        tx.rollback().await.unwrap();
        return failed;
    }
    // 保存article内容
    if let Err(e) = article.save_text() {
        eprintln!("save content error\n{}", e);
        tx.commit().await.unwrap();
        tx.rollback().await.unwrap();
        return failed;
    }

    tx.commit().await.unwrap();
    success
}



